package com.lgcns.weather.info;

import java.util.Arrays;
import java.util.Calendar;

import com.lgcns.weather.util.Util;

/**
 * 단기 예보(오늘~3일간) 정보를 가지고 있는 클래스
 */
public class ShortRangeInfo {
    /** 파싱 성공여부 */
    private boolean ok;
    /** 예보 일시 */
    private String forcastTime;
    /** 데이터 일련번호 : 0부터 시작 */
    private String[] dataSeq;
    /** 시간(24시간) */
    private String[] hour;
    /** 일자 순번(0 ~ 2) */
    private String[] day;
    /** 기온 */
    private String[] temperature;
    /** 최저 기온 */
    private String[] temperatureMin;
    /** 최고 기온 */
    private String[] temperatureMax;
    /** 하늘 상태(1:맑음, 2:구름조금, 3:구름많음, 4:흐림) */
    private String[] sky;
    /** 강수 상태 코드(0:없음, 1:비, 2:비/눈, 3:눈/비, 4:눈) */
    private String[] rainType;
    /** 날씨(한국어) */
    private String[] description;
    /** 강수확률(%) */
    private String[] rainRate;
    /** 예상 강수량 */
    private String[] rainFall;
    /** 예상 적설량 */
    private String[] snowFall;
    /** 풍속(m/s) */
    private String[] windSpeed;
    /** 풍향 코드 */
    private String[] windDirection;
    /** 풍향(한국어) */
    private String[] windDirectionKor;
    /** 습도(%) */
    private String[] humidity;
    /** 배열 생성시 초기화할 길이 */
    private static final int LENGTH = 18;
    /** 실제 데이터 길이. 15~18개 */
    private int dataLength = 0;
    private String[] date;
    private String[] dayOfWeek;
    private String[] dayOfWeekKor = { "일", "월", "화", "수", "목", "금", "토" };

    public ShortRangeInfo() {
        this.ok = true;
        dataSeq = new String[LENGTH];
        hour = new String[LENGTH];
        day = new String[LENGTH];
        temperature = new String[LENGTH];
        temperatureMin = new String[LENGTH];
        temperatureMax = new String[LENGTH];
        sky = new String[LENGTH];
        rainType = new String[LENGTH];
        description = new String[LENGTH];
        rainRate = new String[LENGTH];
        rainFall = new String[LENGTH];
        snowFall = new String[LENGTH];
        windSpeed = new String[LENGTH];
        windDirection = new String[LENGTH];
        windDirectionKor = new String[LENGTH];
        humidity = new String[LENGTH];
    }

    /**
     * 실제 데이터 길이를 얻는다. LENGTH는 18이지만 실제 데이터는 15~18개가 될 수 있다.
     * 
     * @return
     */
    public int getDataLength() {
        if (dataLength == 0) {
            boolean nullExists = false;
            for (int i = 0; i < LENGTH; i++) {
                if (dataSeq[i] == null) {
                    dataLength = i;
                    nullExists = true;
                    break;
                }
            }

            if (!nullExists) {
                dataLength = LENGTH;
            }
        }

        return dataLength;
    }

    /**
     * 데이터 일련번호를 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setDataSeq(int index, String value) {
        dataSeq[index] = value;
    }

    /**
     * 데이터 일련번호를 반환한다.
     * 
     * @param index
     */
    public String getDataSeq(int index) {
        return dataSeq[index];
    }

    /**
     * 시간을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setHour(int index, String value) {
        hour[index] = value;
    }

    /**
     * 시간을 반환한다.
     * 
     * @param index
     */
    public String getHour(int index) {
        return hour[index];
    }

    /**
     * 일자순번(0~2)을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setDay(int index, String value) {
        day[index] = value;
    }

    /**
     * 기온을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setTemperature(int index, String value) {
        String temp = null;
        if (value == null || value.equals("-999.0")) {
            temp = "-";
        } else {
            temp = value;
        }

        temperature[index] = temp;
    }

    /**
     * 기온을 반환한다.
     * 
     * @param index
     */
    public String getTemperature(int index) {
        return temperature[index];
    }

    /**
     * 최저 기온을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setTemperatureMin(int index, String value) {
        String temp = null;
        if (value == null || value.equals("-999.0")) {
            temp = "-";
        } else {
            temp = value;
        }

        temperatureMin[index] = temp;
    }

    /**
     * 최저 기온을 반환한다.
     * 
     * @param index
     */
    public String getTemperatureMin(int index) {
        return temperatureMin[index];
    }

    /**
     * 최고 기온을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setTemperatureMax(int index, String value) {
        String temp = null;
        if (value == null || value.equals("-999.0")) {
            temp = "-";
        } else {
            temp = value;
        }
        temperatureMax[index] = temp;
    }

    /**
     * 최고 기온을 반환한다.
     * 
     * @param index
     */
    public String getTemperatureMax(int index) {
        return temperatureMax[index];
    }

    /**
     * 하늘 상태(1:맑음, 2:구름조금, 3:구름많음, 4:흐림)를 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setSky(int index, String value) {
        sky[index] = value;
    }

    /**
     * 하늘 상태(1:맑음, 2:구름조금, 3:구름많음, 4:흐림)를 반환한다.
     * 
     * @param index
     */
    public String getSky(int index) {
        return sky[index];
    }

    /**
     * 강수 상태 코드(0:없음, 1:비, 2:비/눈, 3:눈/비, 4:눈)를 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setRainType(int index, String value) {
        rainType[index] = value;
    }

    /**
     * 강수 상태 코드(0:없음, 1:비, 2:비/눈, 3:눈/비, 4:눈)를 반환한다.
     * 
     * @param index
     */
    public String getRainType(int index) {
        return rainType[index];
    }

    /**
     * 날씨(한국어)를 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setDescription(int index, String value) {
        description[index] = value;
    }

    /**
     * 날씨(한국어)를 반환한다.
     * 
     * @param index
     */
    public String getDescription(int index) {
        return description[index];
    }

    /**
     * 강수확률(%)을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setRainRate(int index, String value) {
        rainRate[index] = value;
    }

    /**
     * 강수확률(%)을 반환한다.
     * 
     * @param index
     */
    public String getRainRate(int index) {
        return rainRate[index];
    }

    /**
     * 예상 강수량을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setRainFall(int index, String value) {
        Double rain = Util.parseDouble(value);

        if (rain != null) {
            rainFall[index] = Util.formatNumber(rain, "##0.0");
        } else {
            rainFall[index] = "0";
        }
    }

    /**
     * 예상 강수량을 반환한다.
     * 
     * @param index
     */
    public String getRainFall(int index) {
        return rainFall[index];
    }

    /**
     * 예상 적설량을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setSnowFall(int index, String value) {
        snowFall[index] = value;
    }

    /**
     * 예상 적설량을 반환한다.
     * 
     * @param index
     */
    public String getSnowFall(int index) {
        return snowFall[index];
    }

    /**
     * 풍속(m/s)을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setWindSpeed(int index, String value) {
        Double ws = Util.parseDouble(value);

        if (ws != null) {
            windSpeed[index] = Util.formatNumber(ws, "##0.0");
        }
    }

    /**
     * 풍속(m/s)을 반환한다.
     * 
     * @param index
     */
    public String getWindSpeed(int index) {
        return windSpeed[index];
    }

    /**
     * 풍향 코드를 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setWindDirection(int index, String value) {
        windDirection[index] = value;
    }

    /**
     * 풍향 코드를 반환한다.
     * 
     * @param index
     */
    public String getWindDirection(int index) {
        return windDirection[index];
    }

    /**
     * 풍향(한국어)을 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setWindDirectionKor(int index, String value) {
        windDirectionKor[index] = value;
    }

    /**
     * 풍향(한국어)을 반환한다.
     * 
     * @param index
     */
    public String getWindDirectionKor(int index) {
        return windDirectionKor[index];
    }

    /**
     * 습도(%)를 보관한다.
     * 
     * @param index
     * @param value
     */
    public void setHumidity(int index, String value) {
        humidity[index] = value;
    }

    /**
     * 습도(%)를을 반환한다.
     * 
     * @param index
     */
    public String getHumidity(int index) {
        return humidity[index];
    }

    /**
     * 날짜를 반환한다.
     * 
     * @param index
     * @return
     */
    public String getDate(int index) {
        generateDateInfo();
        return date[index];
    }

    /**
     * 요일을 반환한다.
     * 
     * @param index
     * @return
     */
    public String getDayOfWeek(int index) {
        generateDateInfo();
        return dayOfWeek[index];
    }

    /**
     * 날짜, 요일 정보를 생성한다.
     */
    private void generateDateInfo() {
        // 아직 생성되지 않은 경우
        if (date == null || date.length == 0) {
            date = new String[LENGTH];
            dayOfWeek = new String[LENGTH];

            // 주간예보는 발표일 2일 후 부터 6일간 제공
            Calendar cal0 = Util.parseCalendar(forcastTime);
            Calendar cal1 = Util.addDate(cal0, 1);
            Calendar cal2 = Util.addDate(cal1, 1);
            String date0 = Util.getSimpleDate(cal0);
            String date1 = Util.getSimpleDate(cal1);
            String date2 = Util.getSimpleDate(cal2);
            String dayOfWeek0 = dayOfWeekKor[cal0.get(Calendar.DAY_OF_WEEK) - 1];
            String dayOfWeek1 = dayOfWeekKor[cal1.get(Calendar.DAY_OF_WEEK) - 1];
            String dayOfWeek2 = dayOfWeekKor[cal2.get(Calendar.DAY_OF_WEEK) - 1];
            
            boolean firstDate0 = true;
            boolean firstDate1 = true;
            boolean firstDate2 = true;

            for (int i = 0; i < LENGTH; i++) {
                if ("0".equals(day[i])) {
                    if(firstDate0) {
                        date[i] = date0;
                        dayOfWeek[i] = dayOfWeek0;
                        firstDate0 = false;
                    } else {
                        date[i] = "-";
                        dayOfWeek[i] = null;
                    }
                } else if ("1".equals(day[i])) {
                    if(firstDate1) {
                        date[i] = date1;
                        dayOfWeek[i] = dayOfWeek1;
                        firstDate1 = false;
                    } else {
                        date[i] = "-";
                        dayOfWeek[i] = null;
                    }
                } else if ("2".equals(day[i])) {
                    if(firstDate2) {
                        date[i] = date2;
                        dayOfWeek[i] = dayOfWeek2;
                        firstDate2 = false;
                    } else {
                        date[i] = "-";
                        dayOfWeek[i] = null;
                    }
                }
            }
        }
    }

    /**
     * 날씨 코드를 반환한다.
     * 
     * @param index
     * @return
     */
    public String getWeatherCode(int index) {
        Integer skyInt = Util.parseInteger(sky[index]);
        Integer rainTypeInt = Util.parseInteger(rainType[index]);

        String code = null;
        if (skyInt != null && rainTypeInt != null) {
            code = Util.formatNumber(skyInt + rainTypeInt, "00");
        }
        return code;
    }

    /* -------------- default getter / setter --------------- */

    public boolean isOk() {
        return ok;
    }

    public void setOk(boolean ok) {
        this.ok = ok;
    }

    public String getForcastTime() {
        return forcastTime;
    }

    public void setForcastTime(String forcastTime) {
        this.forcastTime = forcastTime;
    }

    @Override
    public String toString() {
        return "ShortRangeInfo [ok=" + ok + ", forcastTime=" + forcastTime + ", dataSeq="
                + Arrays.toString(dataSeq) + ", hour=" + Arrays.toString(hour) + ", day="
                + Arrays.toString(day) + ", temperatureMin=" + Arrays.toString(temperatureMin)
                + ", temperatureMax=" + Arrays.toString(temperatureMax) + ", sky=" + Arrays.toString(sky)
                + ", rainType=" + Arrays.toString(rainType) + ", description=" + Arrays.toString(description)
                + ", rainRate=" + Arrays.toString(rainRate) + ", rainFall=" + Arrays.toString(rainFall)
                + ", snowFall=" + Arrays.toString(snowFall) + ", windSpeed=" + Arrays.toString(windSpeed)
                + ", windDirection=" + Arrays.toString(windDirection) + ", windDirectionKor="
                + Arrays.toString(windDirectionKor) + ", humidity=" + Arrays.toString(humidity) + ", day="
                + Arrays.toString(day) + "]";
    }

}
